package com.chub.study.modules.aop;


import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.map.multi.AbsCollValueMap;
import cn.hutool.core.map.multi.CollectionValueMap;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.chub.RespResult;
import com.chub.study.modules.annotation.DictName;
import com.chub.study.modules.entity.TDictInfo;
import com.chub.study.modules.service.impl.TDictInfoServiceImpl;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author : chub
 * @version : V1.0.0
 * @fileName : DictTranslateAop.java
 * @description : TODO
 * @createTime : 2023-04-11 10:46
 */

@Aspect
@Component
@Slf4j
public class  DictTranslateAop {

    @Autowired
    private TDictInfoServiceImpl dictInfoService;

    @AfterReturning(value = "@annotation(com.chub.study.modules.annotation.DictTranslate)", returning = "result")
    public void serviceAfterReturning(JoinPoint joinPoint, Object result) {
        if (Objects.isNull(result)) {
            return;
        }
        log.info("需要处理的数据， Data:{}", JSON.toJSONString(result));
        try {
            // 这里根据 @DictTranslate 所在方法返回值类型做一下特殊处理
            // 如果是 List 类型，则需要遍历 List 中的每个元素，并对每个元素进行字典名称翻译
            if (result instanceof List) {
                fillListDictName((List)result);
            }
            // 如果是 RespResult 类型，则需要对 RespResult 中的数据进行字典名称翻译
            if (result instanceof RespResult) {

                if (((RespResult<?>) result).getData() instanceof List ) {
                    fillListDictName((List)((RespResult<?>) result).getData());

                }

                // if (((IPage) ((RespResult<?>) result).getData()).getRecords() != null) {
                //     fillListDictName((List)((IPage)((RespResult<?>) result).getData()).getRecords());
                // }
            }
        } catch (Exception ex) {
            log.error("字典名称翻译异常，method:{}", joinPoint.getSignature().getName(), ex);
        }
    }

    private void fillListDictName(List list) throws Exception  {
        if (IterUtil.isEmpty(list)) {
            return;
        }

        Object list0 = list.get(0);
        Field[] fields = list0.getClass().getDeclaredFields();

        // 获取所有带有 @DictName 注解的字段的字段名称
        Set<String> dictFields = Arrays.stream(fields)
                .filter(field -> null != field.getAnnotation(DictName.class))
                .map(field -> field.getAnnotation(DictName.class).filedName())
                .collect(Collectors.toSet());
        log.info("获取所有带有 @DictName 注解的字段的字段名称， dictFields:{}", JSON.toJSONString(dictFields));

        // 获取所有带有 @DictName 注解的字段的字典类型
        Set<String> types = Arrays.stream(fields)
                .filter(field -> null != field.getAnnotation(DictName.class))
                .map(field -> field.getAnnotation(DictName.class).type())
                .collect(Collectors.toSet());
        log.info("获取所有带有 @DictName 注解的字段的字典类型， types:{}", JSON.toJSONString(types));
        if (CollectionUtil.isEmpty(types)) {
            return;
        }

        Map<String, List<TDictInfo>> dictMap = dictInfoService.getBydictTypeCodes(types);

        log.info("字典类型代码查询结果， types:{}, dictMap:{}", JSON.toJSONString(types), JSON.toJSONString(dictMap));

        Table<String, String, String> dictTable = HashBasedTable.create();
        dictMap.forEach((key, val) -> val.forEach(dict -> dictTable.put(key, dict.getDictItemCode(), dict.getDictItemName())));

        list.forEach(obj -> fillObjectDictName(obj, dictTable));

        AbsCollValueMap<String, String, Collection<String>> map = new CollectionValueMap<>();

    }

    private void fillObjectDictName(Object obj, Table<String, String, String> dictTable) {

        Arrays.stream(obj.getClass().getDeclaredFields()).filter(field -> null != field.getAnnotation(DictName.class))
                .forEach(field -> {
                    try {
                        DictName dictName = field.getAnnotation(DictName.class);
                        field.setAccessible(true);
                        Field valField = obj.getClass().getDeclaredField(dictName.filedName());
                        valField.setAccessible(true);

                        if (null == valField.get(obj)) {
                            return;
                        }

                        String fieldVal = String.valueOf(valField.get(obj));
                        if (StrUtil.isNotBlank(dictName.valSeparator())) {
                            List<String> valList = Arrays.stream(StrUtil.splitToArray(fieldVal, dictName.valSeparator()))
                                    .map(val -> dictTable.get(dictName.type(), val)).collect(Collectors.toList());
                            field.set(obj, StrUtil.join(dictName.nameSeparator(), valList));
                        } else {
                            String val = dictTable.get(dictName.type(), fieldVal);
                            field.set(obj, val);
                        }

                    } catch (Exception ex) {
                        log.error("字典名称翻译异常，Object:{}, field:{}", obj.getClass().getSimpleName(), field.getName(), ex);
                    }
                });
    }

}
